package com.example.fengyungo_user.activity.main;

import androidx.annotation.NonNull;

import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.TextView;
import android.widget.Toast;

import com.amap.api.location.AMapLocation;
import com.amap.api.location.AMapLocationClient;
import com.amap.api.location.AMapLocationListener;
import com.amap.api.maps2d.AMap;
import com.amap.api.maps2d.LocationSource;
import com.amap.api.maps2d.MapView;
import com.amap.api.maps2d.model.CameraPosition;
import com.amap.api.services.core.AMapException;
import com.amap.api.services.core.LatLonPoint;
import com.amap.api.services.geocoder.GeocodeResult;
import com.amap.api.services.geocoder.GeocodeSearch;
import com.amap.api.services.geocoder.RegeocodeAddress;
import com.amap.api.services.geocoder.RegeocodeQuery;
import com.amap.api.services.geocoder.RegeocodeResult;
import com.amap.api.services.route.DistanceItem;
import com.amap.api.services.route.DistanceResult;
import com.amap.api.services.route.DistanceSearch;
import com.example.fengyungo_user.R;
import com.example.fengyungo_user.activity.BaseActivity;
import com.example.fengyungo_user.constant.MapConstant;
import com.example.fengyungo_user.utils.MapUtils;

import java.util.ArrayList;
import java.util.List;

/**
 * 地图选点
 *
 * @author 徐
 */
public class PositionSelectActivity extends BaseActivity implements AMapLocationListener, LocationSource, DistanceSearch.OnDistanceSearchListener {

    private static final String TAG = "PositionSelectActivity";

    /**
     * 地图
     */
    private MapView mapView;
    /**
     * 声明AMapLocationClient类对象
     */
    private AMapLocationClient mLocationClient = null;
    /**
     * 地图控制器
     */
    private AMap aMap = null;
    /**
     * 位置更改监听
     */
    private LocationSource.OnLocationChangedListener mListener;
    /**
     * 当前地址
     */
    private String currentPosition;
    /**
     * 选中的位置
     */
    private TextView selectedPosition;
    /**
     * 起点
     */
    private LatLonPoint beginLatLonPoint;
    /**
     * 当前选择的
     */
    private LatLonPoint selectedLatLonPoint;
    /**
     * 起点位置
     */
    private String beginPosition;
    /**
     * DistanceSearch
     */
    private DistanceSearch distanceSearch;
    /**
     * 起点到终点的距离（驾车）
     */
    private float distance;
    /**
     * 距离TextView
     */
    private TextView distanceTv;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_position_select);

        // 获取来自EndActivity的intent携带的数据
        getIntentDataFromEndActivity();

        selectedPosition = findViewById(R.id.tv_selected_position);
        // 确定选择
        Button ok = findViewById(R.id.btn_ok);
        distanceTv = findViewById(R.id.tv_distance);

        // 初始化定位
        mLocationClient = MapUtils.initLocation(this, this);
        // 初始化地图
        initMap(savedInstanceState);
        // 定位
        mLocationClient.startLocation();

        // 初始化测距
        initCalculateRoute();

        // 返回
        ImageButton back = findViewById(R.id.back);
        back.setOnClickListener((view -> {
            finish();
        }));

        // 点击确定按钮
        ok.setOnClickListener((v) -> {
            // 跳转到路线页面
            Intent intent = new Intent(this, RouteActivity.class);
            // 放入起点信息
            intent.putExtra(MapConstant.BEGIN_LAT, beginLatLonPoint.getLatitude());
            intent.putExtra(MapConstant.BEGIN_LON, beginLatLonPoint.getLongitude());
            intent.putExtra(MapConstant.BEGIN_ADDRESS, beginPosition);
            // 终点信息
            intent.putExtra(MapConstant.END_LAT, selectedLatLonPoint.getLatitude());
            intent.putExtra(MapConstant.END_LON, selectedLatLonPoint.getLongitude());
            intent.putExtra(MapConstant.END_ADDRESS, currentPosition);
            // 距离
            intent.putExtra(MapConstant.DISTANCE, distance + MapConstant.DISTANCE_M);
            startActivity(intent);

            Toast.makeText(this, "起点：" + beginPosition, Toast.LENGTH_SHORT).show();
            Toast.makeText(this, "终点：" + currentPosition, Toast.LENGTH_SHORT).show();
            Log.d(TAG, "onCreate: 起点：" + beginLatLonPoint);
            Log.d(TAG, "onCreate: 终点：" + selectedLatLonPoint);
        });
    }

    /**
     * 方法必须重写
     */
    @Override
    public void onResume() {
        super.onResume();
        mapView.onResume();
    }

    /**
     * 方法必须重写
     */
    @Override
    public void onPause() {
        super.onPause();
        mapView.onPause();
    }

    /**
     * 方法必须重写
     */
    @Override
    public void onSaveInstanceState(@NonNull Bundle outState) {
        super.onSaveInstanceState(outState);
        mapView.onSaveInstanceState(outState);
    }

    /**
     * 方法必须重写
     */
    @Override
    public void onDestroy() {
        super.onDestroy();
        mapView.onDestroy();
        //销毁定位客户端，同时销毁本地定位服务。
        Log.d(TAG, "onDestroy: mLocationClient=" + mLocationClient);
        if (mLocationClient != null) {
            mLocationClient.onDestroy();
        }
    }

    /**
     * 获取来自EndActivity的intent携带的数据
     */
    private void getIntentDataFromEndActivity() {
        Intent intent = getIntent();
        double beginLat = intent.getDoubleExtra(MapConstant.BEGIN_LAT, 0);
        double beginLon = intent.getDoubleExtra(MapConstant.BEGIN_LON, 0);
        beginLatLonPoint = new LatLonPoint(beginLat, beginLon);
        beginPosition = intent.getStringExtra(MapConstant.BEGIN_ADDRESS);
        Log.d(TAG, "getIntentDataFromMainFragment: beginLatLonPoint=" + beginLatLonPoint);
    }

    /**
     * 初始化地图
     *
     * @param savedInstanceState Bundle
     */
    private void initMap(Bundle savedInstanceState) {
        mapView = findViewById(R.id.map);
        //创建地图
        mapView.onCreate(savedInstanceState);
        //初始化地图控制器对象
        aMap = mapView.getMap();

        MapUtils.setLocationStyle(aMap);

        MapUtils.setMap(aMap);

        // 设置定位监听
        aMap.setLocationSource(this);
        // 设置为true表示显示定位层并可触发定位，false表示隐藏定位层并不可触发定位，默认是false
        aMap.setMyLocationEnabled(true);

        aMap.setOnMapLoadedListener(() -> {
            MapUtils.addCenterMarker(aMap);
            Log.d(TAG, "onMapLoaded: aMap=" + aMap);
        });
        aMap.setOnCameraChangeListener(new AMap.OnCameraChangeListener() {
            @Override
            public void onCameraChange(CameraPosition cameraPosition) {
            }

            @Override
            public void onCameraChangeFinish(CameraPosition cameraPosition) {
                //开始获取中心点的marker坐标
                try {
                    selectedLatLonPoint = new LatLonPoint(cameraPosition.target.latitude,
                            cameraPosition.target.longitude);
                    startFindPointNameQuery(selectedLatLonPoint, selectedPosition, PositionSelectActivity.this);
                    calculateRouteDistance(selectedLatLonPoint);
                    Log.d(TAG, "onCameraChangeFinish: selectedLatLonPoint=" + selectedLatLonPoint);
                } catch (AMapException e) {
                    e.printStackTrace();
                }
            }
        });
    }

    public void startFindPointNameQuery(final LatLonPoint point, TextView selectedPosition, Context context) throws AMapException {
        //创建一个GeocodeSearch  逆地理编码和地理编码类
        GeocodeSearch search = new GeocodeSearch(context);
        //设置监听器
        search.setOnGeocodeSearchListener(new GeocodeSearch.OnGeocodeSearchListener() {
            @Override
            public void onRegeocodeSearched(RegeocodeResult regeocodeResult, int i) {
                //逆地理编码异步返回
                //由于我们的版本是大于3.2.1 所以成功是1000
                if (i == MapConstant.RESULT_SUCCESS) {
                    //RegeocodeAddress是逆地理编码搜索的地理结果。
                    RegeocodeAddress regeocodeAddress = regeocodeResult.getRegeocodeAddress();
                    Log.d(TAG, "onRegeocodeSearched: regeocodeAddress=" + regeocodeAddress);
                    //逆地理编码返回的格式化地址。
                    currentPosition = regeocodeAddress.getFormatAddress();
                    // 显示当前地址
                    selectedPosition.setText(currentPosition);
                } else {
                    selectedPosition.setText(MapConstant.GET_POSITION_FAILED);
                }

            }

            @Override
            public void onGeocodeSearched(GeocodeResult geocodeResult, int i) {
                //地理编码异步返回
            }
        });
        //point - 要进行逆地理编码的地理坐标点。
        //radius - 查找范围。默认值为1000，取值范围1-3000，单位米。
        //latLonType - 输入参数坐标类型。包含GPS坐标和高德坐标。 GeocodeSearch.AMAP 、GeocodeSearch.GPS
        float radius = 1000F;
        //逆地理RegeocodeQuery构造函数
        RegeocodeQuery regeocodeQuery = new RegeocodeQuery(point, radius, GeocodeSearch.AMAP);
        //发起逆地理编码异步查询
        search.getFromLocationAsyn(regeocodeQuery);
    }

    /**
     * 接收异步返回的定位结果
     *
     * @param aMapLocation AMapLocation
     */
    @Override
    public void onLocationChanged(AMapLocation aMapLocation) {
        if (aMapLocation != null) {
            if (aMapLocation.getErrorCode() == 0) {
                //地址
                currentPosition = aMapLocation.getAddress();
                // 显示起点
                selectedPosition.setText(currentPosition);
                Log.d(TAG, "onLocationChanged: currentPosition=" + currentPosition);
                // 停止定位后，本地定位服务并不会被销毁
                mLocationClient.stopLocation();

                // 显示地图定位结果
                if (mListener != null) {
                    // 显示系统图标
                    mListener.onLocationChanged(aMapLocation);
                }
            } else {
                //定位失败时，可通过ErrCode（错误码）信息来确定失败的原因，errInfo是错误信息，详见错误码表。
                Log.e(TAG, "AmapError location Error, ErrCode:"
                        + aMapLocation.getErrorCode() + ", errInfo:"
                        + aMapLocation.getErrorInfo());
            }
        }
    }

    /**
     * 激活定位
     *
     * @param onLocationChangedListener OnLocationChangedListener
     */
    @Override
    public void activate(OnLocationChangedListener onLocationChangedListener) {
        mListener = onLocationChangedListener;
        if (mLocationClient != null) {
            // 启动定位
            mLocationClient.startLocation();
        }
    }

    /**
     * 停止定位
     */
    @Override
    public void deactivate() {
        mListener = null;
        if (mLocationClient != null) {
            mLocationClient.stopLocation();
            mLocationClient.onDestroy();
        }
        mLocationClient = null;
    }

    /**
     * 初始化测距
     */
    private void initCalculateRoute() {
        // 初始化 DistanceSearch 对象
        try {
            distanceSearch = new DistanceSearch(this);
        } catch (AMapException e) {
            e.printStackTrace();
            // 失败
            Toast.makeText(this, e.getErrorMessage(), Toast.LENGTH_SHORT).show();
        }
        // 设置数据回调监听器
        distanceSearch.setDistanceSearchListener(this);
    }

    /**
     * 发送请求进行测距
     *
     * @param endLatLonPoint 终点
     */
    private void calculateRouteDistance(LatLonPoint endLatLonPoint) {
        DistanceSearch.DistanceQuery distanceQuery = new DistanceSearch.DistanceQuery();
        // 设置搜索参数
        List<LatLonPoint> origins = new ArrayList<>();
        origins.add(beginLatLonPoint);
        distanceQuery.setOrigins(origins);
        distanceQuery.setDestination(endLatLonPoint);
        //设置测量方式，支持直线和驾车
        distanceQuery.setType(DistanceSearch.TYPE_DRIVING_DISTANCE);
        // 发送请求，进行距离测量计算
        distanceSearch.calculateRouteDistanceAsyn(distanceQuery);
    }

    @Override
    public void onDistanceSearched(DistanceResult distanceResult, int i) {
        if (i == MapConstant.RESULT_SUCCESS) {
            // result.getDistanceResults()可以获取到 DistanceItem 列表
            List<DistanceItem> distanceResults = distanceResult.getDistanceResults();
            DistanceItem distanceItem = distanceResults.get(0);
            distance = distanceItem.getDistance();
            distanceTv.setText(MapConstant.DISTANCE_FROM_BEGIN + distance + MapConstant.DISTANCE_M);
        }
    }
}